// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BitlyUrlShortener.cs" company="XamlNinja">
//   2011 Richard Griffin and Ollie Riches
// </copyright>
// <summary>
//    Bitly url shortener
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WP7Contrib.Services.UrlShorteners
{
    using System;
    using System.Reactive.Linq;
    using System.Reactive.Subjects;
    using Communications;
    using Logging;
    using Resources;

    public sealed class BitlyUrlShortener : IShortenUrls
    {
        private const string BitlyUrlFormat = "http://api.bitly.com/v3/shorten?login={0}&apiKey={1}&longUrl={2}&format=json";

        private readonly string login;
        private readonly string apiKey;
        private readonly IHandleResourcesFactory resourceHandlerFactory;

        private readonly IEncodeProperties propertyEncoder;
        private readonly ILog log;
        
        public BitlyUrlShortener(string login, string apiKey) : this(login, apiKey, new ResourceClientFactory(),  new UrlEncoder(), new DebugLog())
        {
        }

        public BitlyUrlShortener(string login, string apiKey, IHandleResourcesFactory resourceHandlerFactory, IEncodeProperties propertyEncoder, ILog log)
        {
            this.login = login;
            this.apiKey = apiKey;
            this.resourceHandlerFactory = resourceHandlerFactory;
            this.propertyEncoder = propertyEncoder;
            this.log = log;
        }

        public IObservable<string> Shorten(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                return Observable.Return(url);
            }

            try
            {
                this.log.Write(string.Format("BitlyUrlShortener: Url - '{0}'.", url));

                var resourceClient = this.resourceHandlerFactory.Create()
                    .ForType(ResourceType.Json)
                    .WithGzip()
                    .UseUrlForGet(BitlyUrlFormat);

                var @params = new[] { this.login, this.apiKey, this.propertyEncoder.Encode(url)};
                var subject = new Subject<string>();

                resourceClient.Get<BitlyResponse>(@params)
                    .Subscribe(response =>
                               {
                                   if (response.StatusCode == "200")
                                   {
                                       this.log.Write(string.Format("BitlyUrlShortener: Shortened url - '{0}'.", response.Data.Url));
                                       subject.OnNext(response.Data.Url);
                                   }
                                   else
                                   {
                                       this.log.Write(string.Format("BitlyUrlShortener: Failed to shorten url..."));
                                       subject.OnNext(response.Data.Url);
                                   }

                                   subject.OnCompleted();
                               },
                               exn =>
                               {
                                   var message = string.Format("BitlyUrlShortener: Failed to shorten url, message - '{0}'.", exn.Message);
                                   this.log.Write(message);

                                   subject.OnNext(url);
                                   subject.OnCompleted();
                               });

                return subject;
            }
            catch (Exception exn)
            {
                var message = string.Format("BitlyUrlShortener: Failed to shorten url, message - '{0}'.", exn.Message);
                this.log.Write(message);
                return Observable.Return(url);
            }
        }
    }
}